﻿using RabbitMQ.Client;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;

namespace ClassLibrary1
{
    public class RabbitMqMessagePublisher : IRabbitMqMessagePublisher
    {
        private readonly IRabbitMqConnectionFactory _connectionFactory;

        public RabbitMqMessagePublisher(IRabbitMqConnectionFactory connectionFactory)
        {
            _connectionFactory = connectionFactory;
        }

        public void Publish<T>(T messageObj) where T : new()
        {
            if (messageObj == null)
            {
                throw new ArgumentNullException(paramName: nameof(messageObj), "参数为空");
            }

            using var channel = _connectionFactory.Connection.CreateModel();
            var attr = messageObj.GetType().GetCustomAttribute<AttAttribute>(inherit: true);
            if (attr == null)
            {
                throw new NullReferenceException(message: "类未自定义特性");
            }
            if (HasCustomExchange(attr!))
            {
                channel.ExchangeDeclare(exchange: attr!.ExchangeName,
                    type: attr!.ExchangeType,
                    durable: false,
                    autoDelete: false,
                    arguments: null
                );
            }

            if (WithoutQueueName(attr!))
            {
                throw new Exception("没有队列名称");
            }

            channel.QueueDeclare(
                queue: attr!.QueueName,
                durable: true,
                exclusive: false,
                autoDelete: false,
                arguments: null
                );
            var message = Newtonsoft.Json.JsonConvert.SerializeObject(messageObj);//messageObj序列化
            var body = System.Text.Encoding.UTF8.GetBytes(message);

            if (WithoutRoutingKey(attr!))
            {
                throw new Exception("没有路由名称");
            }

            channel.BasicPublish(exchange: HasCustomExchange(attr!) ? attr!.ExchangeName : "",
                    routingKey: attr.RoutingKey,
                    basicProperties: null,
                    body: body);

        }

        private static bool HasCustomExchange(AttAttribute attr)
        {
            return !string.IsNullOrWhiteSpace(attr.ExchangeName);
        }

        private static bool WithoutQueueName(AttAttribute attr)
        {
            return string.IsNullOrWhiteSpace(attr.QueueName);
        }

        private static bool WithoutRoutingKey(AttAttribute attr)
        {
            return string.IsNullOrWhiteSpace(attr.RoutingKey);
        }
    }

    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
    public class AttAttribute : Attribute
    {
        public string ExchangeName { get; set; } = "";

        public string QueueName { get; set; }

        public string RoutingKey { get; set; }

        public string ExchangeType { get; set; } = "direct";
    }
}
